﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using CommandPrompt;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using SplashScreenTesting;


namespace Bacon_FTP_Client
{
    /// <summary>
    /// Class that creates the form of the client
    /// </summary>
    public partial class Form1 : Form
    {
        
        #region Properties()

        private MyTreeViews newTreeView = new MyTreeViews();
        private DirectoryInfo dirInfo;
        private Client client;
        public ClientServicesST clientServices;

        private SplashScreen splashScreen;
        private bool done = false;

        #endregion

        #region Constructor()

        /// <summary>
        /// Constructor of the class.
        /// </summary>
        public Form1()
        {
            InitializeComponent();
            this.Load += new EventHandler(HandleFormLoad);
            this.splashScreen = new SplashScreen();
            Directory.SetCurrentDirectory(System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments));
            dirInfo = new DirectoryInfo(System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments));
            ftpCommandPrompt.PromptString = dirInfo.FullName + ">";
        }

        #endregion

        #region SplashScreen

        private void HandleFormLoad(object sender, EventArgs e)
        {
            this.Hide();

            Thread thread = new Thread(new ThreadStart(this.ShowSplashScreen));
            thread.Start();

            Hardworker worker = new Hardworker();
            worker.ProgressChanged += (o, ex) =>
            {
                this.splashScreen.UpdateProgress(ex.Progress);
            };

            worker.HardWorkDone += (o, ex) =>
            {
                done = true;
                this.Show();
            };

            worker.DoHardWork();
        }



        private void ShowSplashScreen()
        {
            splashScreen.Show();
            while (!done)
            {
                Application.DoEvents();
            }
            splashScreen.Close();
            this.splashScreen.Dispose();
        }

        #endregion

        #region Implementation()

        /// <summary>
        /// Event of exit on the toolstripmenu.
        /// </summary>
        /// <param name="sender">Sender of the method</param>
        /// <param name="e">Arguments</param>
        private void salirToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// Method that loads all the objects in the GUI.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {
            newTreeView.createTree(this.localFiles_treeview);
            this.server_treeView.Enabled = false;   
            this.ftpCommandPrompt.Enabled = false;
        }

        /// <summary>
        /// Event before you click on the clients files on the treeview.
        /// </summary>
        /// <param name="sender">Sender of the method</param>
        /// <param name="e">Arguments</param>
        private void localFiles_treeview_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            if (e.Node.Nodes[0].Text == "")
            {
                TreeNode node = newTreeView.EnumerateDirectory(e.Node);
            }
        }

        /// <summary>
        /// Event before you click on the servers files on the treeview.
        /// </summary>
        /// <param name="sender">Sender of the method</param>
        /// <param name="e">Arguments</param>
        private void server_treeView_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            if (e.Node.Nodes[0].Text == "")
            {
                TreeNode node = newTreeView.EnumerateDirectory(e.Node);
            }
        }

        /// <summary>
        /// Event of commands introduction on the prompt.
        /// </summary>
        /// <param name="sender">Sender of the method</param>
        /// <param name="e">Arguments</param>
        private void ftpCommandPrompt_Command(object sender, CommandEventArgs e)
        {
            if (client._conected)
            {
                //ftpCommandPrompt.Refresh();
                //ftpCommandPrompt.ClearMessages();
                ftpCommandPrompt.PromptString = dirInfo.FullName + ">";

                string[] message = CommandProcesing.CommandValidation(e.Command.ToUpper(), e.Parameters, clientServices, client);

                foreach (string msg in message)
	            {
                    if (msg == "null")
                    {
                        ftpCommandPrompt.MessageColor = Color.Red;
                        ftpCommandPrompt.AddMessage("Commando no existe...");
                    }
                    else
                        e.Message = msg; //prints the response

                    //print the commands in the log screen
                    WriteToLog(msg);

                    //Autoscroll the text in the log screen
                    ftpRichTextBox.SelectionStart = ftpRichTextBox.Text.Length;
                    ftpRichTextBox.ScrollToCaret();
                    ftpRichTextBox.Refresh();
                }
            }
            else
            {
                MessageBox.Show("Debe conectarse primero");
            }            
        }

        /// <summary>
        /// Event to connect the client with the server.
        /// </summary>
        /// <param name="sender">Sender of the method</param>
        /// <param name="e">Arguments</param>
        private void connetc_button_Click(object sender, EventArgs e)
        {
            try
            {
                if(!string.IsNullOrEmpty(host_textBox.Text) && !string.IsNullOrEmpty(username_textBox.Text) && !string.IsNullOrEmpty(password_textBox.Text) && !string.IsNullOrEmpty(port_textBox.Text))
                {
                    setClient(host_textBox.Text, username_textBox.Text, password_textBox.Text, port_textBox.Text);
                    clientServices = new ClientServicesST(client);

                    client.SetConnectedStatus(AutenticateUser(clientServices, client));

                    if (client._conected)
                    {
                        //Enable the command prompt
                        this.ftpCommandPrompt.Enabled = true;
                        this.ftpCommandPrompt.ClearMessages();
                        //Enable the server treeview and recreate it
                        this.server_treeView.Enabled = true;
                        this.server_treeView.Nodes.Clear();
                        newTreeView.createTree(this.server_treeView);

                        enableBoxes(false);
                    }
                    else
                    {
                        MessageBox.Show("Fallo la autentificacion...");
                        clientServices.Disconect();
                        return;
                    }                                        
                }
                else
                {
                    MessageBox.Show("Faltan parametros...");
                    return;
                }
            }
            catch (Exception)
            {
                MessageBox.Show("Fallo la coneccion...");
                //throw;
            }
            
        }

        /// <summary>
        /// Funtion to autenticate the client on the server
        /// </summary>
        /// <param name="clientServices">Curren clienService instance</param>
        /// <param name="client">Current client instance</param>
        /// <returns>Returns confirmation</returns>
        private bool AutenticateUser(ClientServicesST clientServices, Client client)
        {
            string[] steps = { "WelcomeMsg", "Username", "Password" };
            string response;
            int counter = 0;

            while (counter != 3)
            {
                response = CommandProcesing.Autenticate(clientServices, client, steps[counter]);

                if (response.Substring(0, 3) == "530" || response.Substring(0, 3) == "421" ||
                    response.Substring(0, 3) == "425" || response.Substring(0, 3) == "426" ||
                    response.Substring(0, 3) == "450")
                {
                    WriteToLog(response);
                    return false;
                }
                else
                    WriteToLog(response);
                
                counter++;
            }

            return true;
        }

        /// <summary>
        /// Function to set the client information.
        /// </summary>
        /// <param name="host">Host IP</param>
        /// <param name="username">Username for the host</param>
        /// <param name="password">Password of the user</param>
        /// <param name="port">Port of the client</param>
        private void setClient(string host, string username, string password, string port) 
        {
            client = new Client(host, username, password, Convert.ToInt16(port));
        }

        /// <summary>
        /// Event for the click of a item in the menustrip.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void top_menuStrip_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {

        }

        /// <summary>
        /// Event that occurs when the disconnect button is pressed and the client is disconnected.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnDisconnect_Click(object sender, EventArgs e)
        {
            WriteToLog(clientServices.DisconnectServer());
            enableBoxes(true);
            //Disable the prompt and the server treeview.
            this.server_treeView.Enabled = false;
            this.ftpCommandPrompt.Enabled = false;
        }

        /// <summary>
        /// Method that disables the boxes and textboxes from the GUI when connected.
        /// </summary>
        /// <param name="state">State (connected or not connected)</param>
        private void enableBoxes(bool state)
        {
            if (state)
            {
                btnDisconnect.SendToBack();
                btnConnect.BringToFront();

                password_textBox.Enabled = true;
                username_textBox.Enabled = true;

                port_textBox.Enabled = true;
                host_textBox.Enabled = true;
            }
            else
            {
                password_textBox.Enabled = false;
                username_textBox.Enabled = false;

                port_textBox.Enabled = false;
                host_textBox.Enabled = false;

                btnConnect.SendToBack();
                btnDisconnect.BringToFront();
            }

        }

        /// <summary>
        /// Event that allows the transmision os the selected file from the treeview from the server.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void fileToLocal_button_Click(object sender, EventArgs e)
        {
            string connectionParameters = clientServices.SendPASVCommand();

            WriteToLog(connectionParameters);

            WriteToLog(clientServices.AttempToReceiveFile(Path.GetFileName(this.server_treeView.SelectedNode.FullPath),
                           Path.GetFullPath(this.server_treeView.SelectedNode.FullPath), connectionParameters, client));
        }

        /// <summary>
        /// Event that allows the transmision of the selected file from the treeview to the server. 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void fileToServer_button_Click(object sender, EventArgs e)
        {
            string connectionParameters = clientServices.SendPASVCommand();

            WriteToLog(connectionParameters);

            WriteToLog(clientServices.AttempToSendFile(Path.GetFileName(this.localFiles_treeview.SelectedNode.FullPath),
                           Path.GetFullPath(this.localFiles_treeview.SelectedNode.FullPath), connectionParameters, client));
        }

        /// <summary>
        /// Method that displays the response from the server. 
        /// </summary>
        private void WriteToLog(string message)
        {
            ftpRichTextBox.Text += message;
        }

        #endregion
    }
}
